package Reproductor;

import javax.media.*;
import javax.swing.*;
import GUI.PanelReproductor;
import java.io.IOException;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;


public class Reproductor {

	/**
	 * Definicion de atributos de la clase reproductor
	 */
	private Player player;
	private Timer tiempo;
	private TimerTask task;
	private int vel = 1000;
	private boolean run = false;
	private int posicion = 0;
	private boolean cancionCargada=false;
	private boolean estaTiempoRestante=false;
	private float volumen=1;
	
	/**
	 * Inicializamos el reproductor.
	 */
	public Reproductor(){
		cancionCargada=false;
		posicion = 0;
	}
	
	/**
	 * Cambia los valores del reproductor para una nueva cancion que se intenta
	 * reproducir.
	 * @param url: direccion donde se halla la cancion
	 * @param barra: barra de desplazamiento.
	 * @param tiempos: tiempo de la cancion
	 */
	public void setReproductor(URL url, JSlider barra, JLabel tiempos){
		try {
			if(cancionCargada){
				Stop(barra, tiempos);
			}
			cancionCargada=true;
			player = Manager.createRealizedPlayer(url);
			player.getGainControl().setLevel(volumen);
			moverBarra(barra, tiempos);
		} 
		catch (NoPlayerException e1) {e1.printStackTrace();} 
		catch (CannotRealizeException e1) {} 
		catch (IOException e1) {}
		
	}
	
	/**
	 * Empieza a reproducirse la cancion
	 */
	public void Play(){
		if(cancionCargada && !run){
			player.start();
			run=true;
		}
	}
	
	/**
	 * Pausa la cancion
	 */
	public void Pause(){
		if(cancionCargada){
			player.stop();
			run=false;
		}
	}
	
	/**
	 * Para la cancion
	 * @param barra: barra de progreso
	 * @param tiempos:tiempo de la cancion
	 */
	public void Stop(JSlider barra, JLabel tiempos){
		if(cancionCargada){
			player.stop();
			player.setMediaTime(new Time(0));
			barra.setValue(0);
			String s = calcularTiempo(0);
			s = s + " / ";
			s = s + calcularDuracion();
			if(estaTiempoRestante){
				tiempos.setText("-" + calcularDuracion());
			}
			tiempos.setText(s);
			run=false;
		}
	}
	
	/**
	 * Mueve la barra de progreso segun avanza la reproduccion
	 * @param barra:barra de progreso
	 * @param tiempos: tiempo de la cancion
	 */
	public void moverBarra(final JSlider barra, final JLabel tiempos){
		if(cancionCargada){
			tiempo = new Timer();
			task = new TimerTask(){
				public void run() { //Math.round
					if(cancionCargada){
						posicion = (int) Math.round(player.getMediaTime().getSeconds()*100/player.getDuration().getSeconds());
						if(player.getMediaTime().getSeconds() >= player.getDuration().getSeconds()){
							Stop(barra, tiempos);
						}
						else{
							barra.setValue(posicion);
							int segundos = (int) player.getMediaTime().getSeconds();
							String s = calcularTiempo(segundos);
							s = s + " / ";
							s = s + calcularDuracion();
							if(estaTiempoRestante){
								int duracion = (int) player.getDuration().getSeconds();
								s = calcularTiempo(duracion-segundos);
								s= "-" + s;
							}
							tiempos.setText(s);
						}
					}
				}
			};
			tiempo.schedule(task,0,vel);
		}
	}
	
	/**
	 * Rebobina la cancion hasta el punto seleccionado por el usuario.
	 * @param p:posicion a la que queremos rebobinar.
	 * @param barra: barra de progreso
	 * @param tiempos: tiempo de la cancion.
	 */
	public void rebobinar(int p, JSlider barra, JLabel tiempos){
		if(cancionCargada){
			double temp = (double) Math.round(p*player.getDuration().getSeconds()/100);
			player.setMediaTime(new Time(temp));
			moverBarra(barra, tiempos);
		}
	}
	
	/**
	 * Traduce el tiempo a una cadena de caracteres.
	 * @param tiempo: tiempo original.
	 * @return cadena que representa lo mismo que el parametro de entrada pero en 
	 * forma de cadena de caracteres.
	 */
	public String calcularTiempo(int tiempo) {
		String aux;
		int segundos=tiempo;
		int minutos=0;
		int horas=0;
		if(tiempo>60){
			minutos=segundos/60;
			segundos = segundos % 60;	
		}
		if(tiempo>60){
			horas=minutos/60;
			minutos = minutos % 60;
		}
		aux=""+horas+":";
		if(minutos<10){
			aux=aux+"0";
		}
		aux=aux+minutos+":";
		if(segundos<10){
			aux=aux+"0";
		}
		aux=aux+segundos;
		return aux;
	}
	
	/**
	 * Calcula el tiempo que lleva reproduciendose la cancion.
	 * @return: cadena de caracteres que representa ese tiempo
	 */
	public String calcularDuracion(){
		int tiempo = (int) player.getDuration().getSeconds();
		return calcularTiempo(tiempo);
	}
	
	/**
	 * Muestra el tiempo que lleva reproduciendose la cancion
	 * @param estaTiempoRest:booleano que indica si queda tiempo restante o no.
	 * @param tiempos:tiempo de la cancion
	 */
	public void modificarTiempos(boolean estaTiempoRest, JLabel tiempos) {
		estaTiempoRestante = estaTiempoRest;
		int segundos = (int) player.getMediaTime().getSeconds();
		String s = calcularTiempo(segundos);
		s = s + " / ";
		s = s + calcularDuracion();
		if(estaTiempoRestante){
			int duracion = (int) player.getDuration().getSeconds();
			s = calcularTiempo(duracion-segundos);
			s= "-" + s;
		}
		tiempos.setText(s);
	}
	
	/**
	 * Deshabilita el sonido al reproductor
	 * @param b: booleano que indica si queremos deshabilitarlo o no.
	 */
	public void silenciar(boolean b) {
		if(cancionCargada){
			player.getGainControl().setMute(b);
		}
	}
	
	/**
     *Varia el volumen de sonido del reproductor
	 * @param x: volumen al que lo vamos a cambiar.
	 */
	public void cambiarVolumen(float x) {
		volumen=x;
		if(cancionCargada){
			player.getGainControl().setLevel(volumen);
		}
	}
	
	/**
	 * Se fija un booleano, que indica si hay cargada una cancion o no, a true o false
	 * en funcion del parametro de entrada
	 * @param b: booleano que indica si hay cancion cargada o no.
	 */
	public void setCancionCargada(boolean b){
		cancionCargada=b;
	}
	
	/**
	 * Devuelve un booleano indicando si hay una cancion cargada en el reproductor
	 * o no
	 * @return true si hay cancion cargada, false si no.
	 */
	public boolean getCancionCargada(){
		return cancionCargada;
	}

}
